/*
 * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
 * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
 * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
 * Vestibulum commodo. Ut rhoncus gravida arcu.
 */

package com.zhipin.planck;

import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.List;

/**
 * @author xieqing
 * @email xieqing@kanzhun.com
 * @description
 * @date 2024-02-20 16:59
 */
public class CidLoadBalance extends AbstractLoadBalance {
    public static final String NAME = "random";
    private Logger logger = LoggerFactory.getLogger(CidLoadBalance.class);

    public CidLoadBalance() {
    }


    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        int length = invokers.size();
        if (length <= 0) {
            return null;
        } else {
            Object argument = invocation.getArguments()[0];
            long cid = getCid(argument);
            String ip = ChannelSessionUtil.getIpByChannelId(cid);
            Iterator var8 = invokers.iterator();

            while (var8.hasNext()) {
                Invoker<T> invoker = (Invoker) var8.next();
                String invokerIp = invoker.getUrl().getIp();
                if (StringUtils.equals(ip, invokerIp)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("use invoker = " + invoker + ", ip = " + invokerIp);
                    }

                    return invoker;
                }
            }

            logger.warn("not found right invocation!!!!! cid=" + cid + ", ip=" + ip);

            throw new IllegalArgumentException("not found right invocation error");
        }
    }

    private long getCid(Object argument) {
        Class<?> clazz = argument.getClass();
        Field declaredField = null;
        try {
            declaredField = clazz.getDeclaredField("cid_");
            declaredField.setAccessible(true);
            return declaredField.get(argument) == null ? 0 : (Long) declaredField.get(argument);
        } catch (Exception e) {
            logger.error("get cid error", e);
            throw new RuntimeException(e);
        }
    }


}
